package util

import (
	"encoding/json"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"

	"github.com/pkg/errors"
)

// JSONMaxFileSize is the max size of json file at most 10M
const JSONMaxFileSize = 10 * 1024 * 1024

// CheckFileInfoAndSize check whether the file exists, is regular file, and if its size exceeds limit
func CheckFileInfoAndSize(path string, sizeLimit int64) error {
	f, err := os.Stat(filepath.Clean(path))
	if err != nil {
		return err
	}
	if !f.Mode().IsRegular() {
		return errors.Errorf("file %s should be a regular file", f.Name())
	}

	if f.Size() == 0 {
		return errors.Errorf("file %s is empty", f.Name())
	}
	if f.Size() > sizeLimit {
		return errors.Errorf("file %s size is: %d, exceeds limit %d", f.Name(), f.Size(), sizeLimit)
	}

	return nil
}

// LoadJSONFile load json files and store it into v
func LoadJSONFile(file string, v interface{}) error {
	err := CheckFileInfoAndSize(file, JSONMaxFileSize)
	if err != nil {
		return err
	}

	f, err := ioutil.ReadFile(file) // nolint: gosec
	if err != nil {
		return err
	}

	return json.Unmarshal(f, v)
}

// ExecCmdOutput execute cmd received and return the output and error if any
func ExecCmdOutput(name string, args ...string) ([]byte, error) {
	execPath, err := exec.LookPath(name)
	if err != nil {
		return nil, err
	}

	cmd := exec.Command(execPath, args...)
	output, err := cmd.Output()
	if err != nil {
		err = errors.Errorf("exec command %v %v failed: %v, output: %v",
			execPath, args, err, string(output))
		return output, err
	}

	return output, err
}
